www.gusucode.com > VC++ 模仿MSN界面 > VC++ 模仿MSN界面/gusucode/MSN/SplitterControl.cpp
//Download by http://www.NewXing.com // SplitterControl.cpp : implementation file // #include "stdafx.h" #include "SplitterControl.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CSplitterControl // hCursor1 is for vertiacal one // and hCursor2 is for horizontal one static HCURSOR SplitterControl_hCursor1 = NULL; static HCURSOR SplitterControl_hCursor2 = NULL; CSplitterControl::CSplitterControl() { // Mouse is pressed down or not ? m_bIsPressed = FALSE; // Min and Max range of the splitter. m_nMin = m_nMax = -1; } CSplitterControl::~CSplitterControl() { } BEGIN_MESSAGE_MAP(CSplitterControl, CStatic) //{{AFX_MSG_MAP(CSplitterControl) ON_WM_PAINT() ON_WM_MOUSEMOVE() ON_WM_SETCURSOR() ON_WM_LBUTTONDOWN() ON_WM_LBUTTONUP() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CSplitterControl message handlers /**************************************************** * Create(DWORD dwStyle, const CRect& rect, CWnd* pParent, nID) * Use this function instead of the CStatic::Create function * Parameters: No need to explain (see MSDN (:-) ) * ****************************************************/ void CSplitterControl::Create(DWORD dwStyle, const CRect &rect, CWnd *pParent, UINT nID) { CRect rc = rect; dwStyle |= SS_NOTIFY; // Determine default type base on it's size. m_nType = (rc.Width() < rc.Height())? SPS_VERTICAL: SPS_HORIZONTAL; if (m_nType == SPS_VERTICAL) rc.right = rc.left + 5; else // SPS_HORIZONTAL rc.bottom = rc.top + 5; CStatic::Create("", dwStyle, rc, pParent, nID); if (!SplitterControl_hCursor1) { SplitterControl_hCursor1 = AfxGetApp()->LoadStandardCursor(IDC_SIZEWE); SplitterControl_hCursor2 = AfxGetApp()->LoadStandardCursor(IDC_SIZENS); } // force the splitter not to be splited. SetRange(0, 0); } // Set style for splitter control // nStyle = SPS_VERTICAL or SPS_HORIZONTAL int CSplitterControl::SetStyle(int nStyle) { int m_nOldStyle = m_nType; m_nType = nStyle; return m_nOldStyle; } int CSplitterControl::GetStyle() { return m_nType; } void CSplitterControl::OnPaint() { CPaintDC dc(this); // device context for painting CRect rcClient; GetClientRect(rcClient); CBrush br, *pOB; CPen pen, *pOP; dc.Draw3dRect(rcClient, RGB(255, 255, 255), RGB(255, 255, 255)); rcClient.DeflateRect(1,1,1,1); pen.CreatePen(0, 1, RGB(255, 255, 255)); br.CreateSolidBrush(RGB(255, 255, 255)); pOB = dc.SelectObject(&br); pOP = dc.SelectObject(&pen); dc.Rectangle(rcClient); // Restore pen and brush DeleteObject(dc.SelectObject(pOB)); DeleteObject(dc.SelectObject(pOP)); } void CSplitterControl::OnMouseMove(UINT nFlags, CPoint point) { if (m_bIsPressed) { CWindowDC dc(NULL); DrawLine(&dc, m_nX, m_nY); CPoint pt = point; ClientToScreen(&pt); GetParent()->ScreenToClient(&pt); //CWnd* pParent = pWnd->GetParent(); if (pt.x < m_nMin) pt.x = m_nMin; if (pt.y < m_nMin) pt.y = m_nMin; if (pt.x > m_nMax) pt.x = m_nMax; if (pt.y > m_nMax) pt.y = m_nMax; GetParent()->ClientToScreen(&pt); m_nX = pt.x; m_nY = pt.y; DrawLine(&dc, m_nX, m_nY); } CStatic::OnMouseMove(nFlags, point); } BOOL CSplitterControl::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) { if (nHitTest == HTCLIENT) { (m_nType == SPS_VERTICAL)?(::SetCursor(SplitterControl_hCursor1)) :(::SetCursor(SplitterControl_hCursor2)); return 0; } else return CStatic::OnSetCursor(pWnd, nHitTest, message); } void CSplitterControl::OnLButtonDown(UINT nFlags, CPoint point) { CStatic::OnLButtonDown(nFlags, point); m_bIsPressed = TRUE; SetCapture(); CRect rcWnd; GetWindowRect(rcWnd); if (m_nType == SPS_VERTICAL) m_nX = rcWnd.left + rcWnd.Width() / 2; else m_nY = rcWnd.top + rcWnd.Height() / 2; if (m_nType == SPS_VERTICAL) m_nSavePos = m_nX; else m_nSavePos = m_nY; CWindowDC dc(NULL); DrawLine(&dc, m_nX, m_nY); } void CSplitterControl::OnLButtonUp(UINT nFlags, CPoint point) { if (m_bIsPressed) { ClientToScreen(&point); CWindowDC dc(NULL); DrawLine(&dc, m_nX, m_nY); CPoint pt(m_nX, m_nY); m_bIsPressed = FALSE; CWnd *pOwner = GetOwner(); if (pOwner && IsWindow(pOwner->m_hWnd)) { CRect rc; int delta; pOwner->GetClientRect(rc); pOwner->ScreenToClient(&pt); MoveWindowTo(pt); if (m_nType == SPS_VERTICAL) delta = m_nX - m_nSavePos; else delta = m_nY - m_nSavePos; SPC_NMHDR nmsp; nmsp.hdr.hwndFrom = m_hWnd; nmsp.hdr.idFrom = GetDlgCtrlID(); nmsp.hdr.code = SPN_SIZED; nmsp.delta = delta; pOwner->SendMessage(WM_NOTIFY, nmsp.hdr.idFrom, (LPARAM)&nmsp); } } CStatic::OnLButtonUp(nFlags, point); ReleaseCapture(); } void CSplitterControl::DrawLine(CDC* pDC, int x, int y) { int nRop = pDC->SetROP2(R2_NOTXORPEN); CRect rcWnd; int d = 1; GetWindowRect(rcWnd); CPen pen; pen.CreatePen(0, 1, RGB(20, 20, 20)); CPen *pOP = pDC->SelectObject(&pen); if (m_nType == SPS_VERTICAL) { pDC->MoveTo(m_nX - d, rcWnd.top); pDC->LineTo(m_nX - d, rcWnd.bottom); pDC->MoveTo(m_nX + d, rcWnd.top); pDC->LineTo(m_nX + d, rcWnd.bottom); } else // m_nType == SPS_HORIZONTAL { pDC->MoveTo(rcWnd.left, m_nY - d); pDC->LineTo(rcWnd.right, m_nY - d); pDC->MoveTo(rcWnd.left, m_nY + d); pDC->LineTo(rcWnd.right, m_nY + d); } pDC->SetROP2(nRop); pDC->SelectObject(pOP); } void CSplitterControl::MoveWindowTo(CPoint pt) { CRect rc; GetWindowRect(rc); CWnd* pParent; pParent = GetParent(); if (!pParent || !::IsWindow(pParent->m_hWnd)) return; pParent->ScreenToClient(rc); if (m_nType == SPS_VERTICAL) { int nMidX = (rc.left + rc.right) / 2; int dx = pt.x - nMidX; rc.OffsetRect(dx, 0); } else { int nMidY = (rc.top + rc.bottom) / 2; int dy = pt.y - nMidY; rc.OffsetRect(0, dy); } MoveWindow(rc); } void CSplitterControl::ChangeWidth(CWnd *pWnd, int dx, DWORD dwFlag) { CWnd* pParent = pWnd->GetParent(); if (pParent && ::IsWindow(pParent->m_hWnd)) { CRect rcWnd; pWnd->GetWindowRect(rcWnd); pParent->ScreenToClient(rcWnd); if (dwFlag == CW_LEFTALIGN) rcWnd.right += dx; else if (dwFlag == CW_RIGHTALIGN) rcWnd.left -= dx; pWnd->MoveWindow(rcWnd); } } void CSplitterControl::ChangeHeight(CWnd *pWnd, int dy, DWORD dwFlag) { CWnd* pParent = pWnd->GetParent(); if (pParent && ::IsWindow(pParent->m_hWnd)) { CRect rcWnd; pWnd->GetWindowRect(rcWnd); pParent->ScreenToClient(rcWnd); if (dwFlag == CW_TOPALIGN) rcWnd.bottom += dy; else if (dwFlag == CW_BOTTOMALIGN) rcWnd.top -= dy; pWnd->MoveWindow(rcWnd); } } void CSplitterControl::ChangePos(CWnd* pWnd, int dx, int dy) { CWnd* pParent = pWnd->GetParent(); if (pParent && ::IsWindow(pParent->m_hWnd)) { CRect rcWnd; pWnd->GetWindowRect(rcWnd); pParent->ScreenToClient(rcWnd); rcWnd.OffsetRect(-dx, dy); pWnd->MoveWindow(rcWnd); } } void CSplitterControl::SetRange(int nMin, int nMax) { m_nMin = nMin; m_nMax = nMax; }